home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / macabuse / imlib / filter.c < prev    next >
C/C++ Source or Header  |  1997-05-20  |  5KB  |  240 lines

  1. #include "image.hpp"
  2. #include "macs.hpp"
  3. #include "filter.hpp"
  4.  
  5. extern unsigned char current_background;
  6.  
  7. filter::filter(palette *from, palette *to)   // creates a conversion filter from one palette to another
  8. {
  9.   nc=from->pal_size() > to->pal_size() ? from->pal_size() : to->pal_size();
  10.   unsigned char *p=fdat=(unsigned char *)jmalloc(nc,"conversion filter");
  11.   unsigned char *r,*g,*b;
  12.   r=g=b=(unsigned char *)from->addr();
  13.   g++;
  14.   b+=2;
  15.  
  16.   int dk=to->darkest(1);
  17.   for (int i=0;i<nc;i++,p++,r+=3,g+=3,b+=3)
  18.   {
  19.     *p=to->find_closest(*r,*g,*b);
  20.  
  21.     // make sure non-blacks don't get remapped to the transparency
  22.     if ((*r!=0 || *g!=0 || *b!=0) && (to->red(*p)==0 && to->green(*p)==0 && to->blue(*p)==0))
  23.       *p=dk;
  24.   }
  25.  
  26. }
  27.  
  28. void filter::clear()
  29. {
  30.   int i;
  31.   for (i=0;i<nc;i++)
  32.     fdat[i]=i;
  33. }
  34.  
  35. void filter::max_threshold(int minv, char blank)
  36. {
  37.   int i;
  38.   CONDITION(minv>=0 && minv<nc,"Bad minv");
  39.   for (i=0;i<minv;i++)
  40.     fdat[i]=blank;
  41. }
  42.  
  43. void filter::min_threshold(int maxv, char blank)
  44. {
  45.   int i;
  46.   CONDITION(maxv>=0 && maxv<nc,"bad maxv value in filter::max_thresh");
  47.   for (i=nc-1;i>=maxv;i--)
  48.     fdat[i]=(unsigned) blank;
  49. }
  50.  
  51.  
  52. void filter::set(int color_num, char change_to)
  53. {
  54.   CONDITION(color_num>=0 && color_num<nc,"Bad colors_num");
  55.   fdat[color_num]=(unsigned) change_to;
  56. }
  57.  
  58.  
  59. filter::filter(int colors)
  60. {
  61.   CONDITION(colors>=0 && colors<=256,"bad colors value");
  62.   nc=colors;
  63.   make_block(nc);
  64.   fdat=(unsigned char *)jmalloc(nc,"filter");
  65.   clear();
  66. }
  67.  
  68. void filter::apply(image *im)
  69. {
  70.   int x,y;
  71.   unsigned char *c;
  72.   CONDITION(im,"null image passed in filter::apply\n");
  73.   for (y=im->height()-1;y>=0;y--)
  74.   {
  75.     c=im->scan_line(y);
  76.     for (x=im->width()-1;x>=0;x--)
  77.     {
  78.       CONDITION((unsigned) c[x]<nc,"not enough filter colors");
  79.       c[x]=fdat[(unsigned) c[x]];
  80.     }
  81.   }
  82. }
  83.  
  84.  
  85. palette *compare_pal;
  86.  
  87. int color_compare(void *c1, void *c2)
  88. {
  89.   long v1,v2;  
  90.   unsigned char r1,g1,b1,r2,g2,b2;
  91.   compare_pal->get(  *((unsigned char *)c1),r1,g1,b1);
  92.   compare_pal->get(  *((unsigned char *)c2),r2,g2,b2);
  93.   v1=(int)r1*(int)r1+(int)g1*(int)g1+(int)b1*(int)b1;
  94.   v2=(int)r2*(int)r2+(int)g2*(int)g2+(int)b2*(int)b2;
  95.   if (v1<v2) return -1;
  96.   else if (v1>v2) return 1;
  97.   else return 0;     
  98. }
  99.  
  100.  
  101. /*color_filter::color_filter(palette *pal, int color_bits)
  102. {
  103.   unsigned char map[256],*last_start,*start;
  104.   int i,last_color=0,color;
  105.   compare_pal=pal;  
  106.   for (i=0;i,256;i++)
  107.     map[i]=i;
  108.  
  109.   qsort(map,1,1,color_compare); 
  110.   colors=1<<color_bits;
  111.   last_start=color_table=(unsigned char *)malloc(colors*colors*colors);
  112.  
  113.   
  114.  
  115.   last_color=map[0];
  116.   last_dist=0;
  117.   
  118.   
  119.   for (i=1;i<colors;i++)
  120.   {   
  121.     color=map[i<<(8-color_bits)];
  122.     dist=       
  123.  
  124.     memset(c,
  125.   }
  126.   
  127.   
  128. }*/
  129.  
  130.  
  131. color_filter::color_filter(palette *pal, int color_bits, void (*stat_fun)(int))
  132.   color_bits=5;      // hard code 5 for now
  133.   int r,g,b,rv,gv,bv,
  134.       c,i,max=pal->pal_size(),
  135.       lshift=8-color_bits;
  136.   unsigned char *pp;
  137.   
  138.   long dist_sqr,best;
  139.   int colors=1<<color_bits;
  140.   color_table=(unsigned char *)jmalloc(colors*colors*colors,"color_filter");
  141.   for (r=0;r<colors;r++)
  142.   {
  143.     if (stat_fun) stat_fun(r);
  144.     rv=r<<lshift;    
  145.     for (g=0;g<colors;g++)
  146.     {
  147.       gv=g<<lshift;      
  148.       for (b=0;b<colors;b++)
  149.       {
  150.     bv=b<<lshift;      
  151.         best=0x7fffffff;
  152.         for (i=0,pp=(unsigned char *)pal->addr();i<max;i++)
  153.         { 
  154.           register long rd=*(pp++)-rv,
  155.                         gd=*(pp++)-gv,
  156.                         bd=*(pp++)-bv;
  157.       
  158.           dist_sqr=(long)rd*rd+(long)bd*bd+(long)gd*gd;
  159.           if (dist_sqr<best)
  160.           { best=dist_sqr;
  161.             c=i;
  162.           }
  163.         }
  164.         color_table[r*colors*colors+g*colors+b]=c;
  165.       }
  166.     }
  167.   }  
  168. }
  169.  
  170. color_filter::color_filter(spec_entry *e, bFILE *fp)
  171. {
  172.   fp->seek(e->offset,0);
  173.   fp->read_short();
  174.   int colors=32;
  175.   color_table=(unsigned char *)jmalloc(colors*colors*colors,"color_filter : loaded");
  176.   fp->read(color_table,colors*colors*colors);
  177. }
  178.  
  179. int color_filter::size()
  180. {
  181.   int colors=32;
  182.   return 2+colors*colors*colors;
  183. }
  184.  
  185. int color_filter::write(bFILE *fp)
  186. {
  187.   int colors=32;
  188.   fp->write_short(colors);
  189.   return fp->write(color_table,colors*colors*colors)==colors*colors*colors;
  190. }
  191.  
  192.  
  193. void filter::put_image(image *screen, image *im, short x, short y, char transparent)
  194. {
  195.   short cx1,cy1,cx2,cy2,x1=0,y1=0,x2=im->width()-1,y2=im->height()-1;
  196.   screen->get_clip(cx1,cy1,cx2,cy2);
  197.   
  198.   // see if the image gets clipped of the screen
  199.   if (x>cx2 || y>cy2 || x+(x2-x1)<cx1 || y+(y2-y1)<cy1) return ;
  200.   
  201.   if (x<cx1)
  202.   { x1+=(cx1-x); x=cx1; }
  203.   if (y<cy1)
  204.   { y1+=(cy1-y); y=cy1; }
  205.  
  206.   if (x+x2-x1+1>cx2)
  207.   { x2=cx2-x+x1; }
  208.  
  209.   if (y+y2-y1+1>cy2)
  210.   { y2=cy2-y+y1; }
  211.   if (x1>x2 || y1>y2) return ;    
  212.  
  213.   
  214.  
  215.  
  216.   int xl=x2-x1+1;
  217.   int yl=y2-y1+1;
  218.  
  219.   screen->add_dirty(x,y,x+xl-1,y+yl-1);
  220.  
  221.   uchar *pg1=screen->scan_line(y),*source,*dest;
  222.   uchar *pg2=im->scan_line(y1);
  223.   int i;
  224.   for (int j=0;j<yl;j++)        
  225.   {
  226.     for (i=0,source=&pg2[x1],dest=&pg1[x];i<xl;i++,source++,dest++)    
  227.       if (!transparent || *source!=current_background) 
  228.         *dest=fdat[*source];
  229.     pg1=screen->next_line(y+j,pg1);  
  230.     pg2=im->next_line(y1+j,pg2);
  231.   }
  232.  
  233. }
  234.  
  235.  
  236.  
  237.  
  238.  
  239.